iT邦幫忙

2024 iThome 鐵人賽

DAY 10
0

今天我們將學習投資組合的概念,並實作一個簡單的多資產投資組合。投資組合能夠分散投資風險,通過將資金配置到不同資產類別中,降低單一資產波動對整體投資的影響。今日 Colab


一、投資組合的概念

1. 什麼是投資組合?

投資組合是將資金配置於多種資產類別(如股票債券黃金房地產現金等)以達到分散風險並實現收益最大化的投資策略。多資產投資組合的核心是平衡風險和回報,確保在市場波動時仍然能夠維持相對穩定的收益。但需要注意分散投資的標的需要好好思考,如果都是同一類型可能沒有到分散的目的
https://ithelp.ithome.com.tw/upload/images/20240923/201205494yPVk13Ven.jpg

2. 投資組合的優勢

  • 分散風險:通過將資金分散到不同資產,降低單一資產對投資組合整體的影響。
  • 降低波動:不同資產類別的相關性通常較低,當一部分資產下跌時,其他資產可能上漲,從而降低整體波動。
  • 提高風險調整後收益:通過合理的資產配置,能夠在不增加風險的情況下,實現更高的收益。

二、實現簡單的多資產投資組合

我們將使用 Backtrader 來實作一個包含多種資產(例如蘋果股票 AAPL、谷歌股票 GOOGL 和黃金 ETF GLD)的簡單投資組合。

1. 準備數據

首先,我們將從 yfinance 下載所需的資產數據。

import backtrader as bt
import yfinance as yf
from datetime import datetime

# 下載多資產的數據
symbols = ['AAPL', 'GOOGL', 'GLD']
data_feeds = []

for symbol in symbols:
    data = yf.download(symbol, start="2010-01-01", end="2020-01-01")
    data_feed = bt.feeds.PandasData(dataname=data)
    data_feeds.append(data_feed)

2. 定義多資產投資組合策略

我們將創建一個簡單的策略,將資金平均分配到每個資產中。這裡我們使用 backtrader 的內建功能來實現這一策略:

class MultiAssetStrategy(bt.Strategy):
    def __init__(self):
        self.size = 0  # 用於保存每個資產的持倉量

    def next(self):
        # 在第一次運行時,根據現有現金分配資金
        if self.size == 0:
            cash = self.broker.getcash()
            per_asset_cash = cash / len(self.datas)  # 平均分配每個資產的資金

            for data in self.datas:
                size = int(per_asset_cash / data.close[0])  # 根據每個資產的價格計算要買入的數量
                self.buy(data=data, size=size)

                self.size += size  # 更新持倉量

3. 執行多資產投資組合回測

# 初始化 Cerebro 回測引擎
cerebro = bt.Cerebro()
cerebro.addstrategy(MultiAssetStrategy)

# 添加多個資產數據
for data_feed in data_feeds:
    cerebro.adddata(data_feed)

# 設定初始資金
cerebro.broker.setcash(100000.0)

# 執行回測
print(f'初始資金: {cerebro.broker.getvalue():.2f}')
cerebro.run()
print(f'回測後資金: {cerebro.broker.getvalue():.2f}')
cerebro.plot(iplot=False)

可得下面結果,依序為三種資產的買賣:
https://ithelp.ithome.com.tw/upload/images/20240923/20120549EqfOyUETdB.png

三、結果分析與優化

在運行此策略後,我們可以看到資金隨著時間的變化,以及多資產投資組合的總體表現。接下來可以考慮進行以下優化:

  • 資產配置優化:根據資產的歷史表現與風險,調整每個資產的權重。例如,可以根據均值-方差模型(Markowitz)進行資產配置,或使用風險平價(Risk Parity)方法。
  • 動態調整資產:根據市場條件,定期調整資產配置比例,實現更好的風險與收益平衡。

四、與單一資產的比較

我們與單一資產來做比較,如下程式,也可去 Colab 來直接執行:

# Re-import necessary libraries
import backtrader as bt
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime

# 下載多資產的數據
symbols = ['AAPL', 'GOOGL', 'GLD']
data_feeds = {}

for symbol in symbols:
    data = yf.download(symbol, start="2010-01-01", end="2020-01-01")
    data_feeds[symbol] = bt.feeds.PandasData(dataname=data)

# 建立多資產投資組合策略
class MultiAssetStrategy(bt.Strategy):
    def __init__(self):
        self.size = 0  # 用於保存每個資產的持倉量
        self.daily_value = []  # 用於記錄每日投資組合價值

    def next(self):
        # 在第一次運行時,根據現有現金分配資金
        if self.size == 0:
            cash = self.broker.getcash()
            per_asset_cash = cash / len(self.datas)  # 平均分配每個資產的資金

            for data in self.datas:
                size = int(per_asset_cash / data.close[0])  # 根據每個資產的價格計算要買入的數量
                self.buy(data=data, size=size)
                self.size += size  # 更新持倉量

        self.daily_value.append(self.broker.getvalue())  # 記錄每日投資組合價值

# 建立單一資產投資策略
class SingleAssetStrategy(bt.Strategy):
    def __init__(self):
        self.size = 0  # 用於保存持倉量
        self.daily_value = []  # 用於記錄每日投資組合價值

    def next(self):
        if self.size == 0:
            cash = self.broker.getcash()
            size = int(cash / self.datas[0].close[0])
            self.buy(data=self.datas[0], size=size)
            self.size += size

        self.daily_value.append(self.broker.getvalue())  # 記錄每日投資組合價值

# 初始化 Cerebro 回測引擎
def run_strategy(strategy_class, data_feed):
    cerebro = bt.Cerebro()
    cerebro.addstrategy(strategy_class)
    cerebro.adddata(data_feed)
    cerebro.broker.setcash(100000.0)
    result = cerebro.run()
    return result[0].daily_value  # 返回每日投資組合價值

# 執行多資產策略的回測,並記錄每日資產價值
multi_asset_values = run_strategy(MultiAssetStrategy, data_feeds['AAPL'])
for symbol in ['GOOGL', 'GLD']:
    cerebro = bt.Cerebro()
    cerebro.adddata(data_feeds[symbol])
    cerebro.addstrategy(MultiAssetStrategy)
    cerebro.broker.setcash(100000.0)
    result = cerebro.run()
    multi_asset_values = [x + y for x, y in zip(multi_asset_values, result[0].daily_value)]

multi_asset_values = [x / 3 for x in multi_asset_values]  # 計算多資產每日的平均值

# 執行每一種單一資產策略的回測
single_asset_values = {}
for symbol in symbols:
    single_asset_values[symbol] = run_strategy(SingleAssetStrategy, data_feeds[symbol])

# 計算波動率
def calculate_volatility(daily_values):
    returns = pd.Series(daily_values).pct_change().dropna()
    volatility = returns.std() * np.sqrt(252)  # 年化波動率
    return volatility

multi_asset_volatility = calculate_volatility(multi_asset_values)
single_asset_volatilities = {symbol: calculate_volatility(values) for symbol, values in single_asset_values.items()}
print("single_asset_volatilities",single_asset_volatilities)

# 視覺化結果
plt.figure(figsize=(14, 6))

# 資產最終價值比較
final_values = [multi_asset_values[-1]] + [single_asset_values[symbol][-1] for symbol in symbols]
plt.subplot(1, 2, 1)
plt.bar(['Multi-Asset'] + symbols, final_values, color=['blue', 'green', 'red', 'orange'])
plt.title('Final Portfolio Values')
plt.ylabel('Value ($)')

# 波動率比較
volatilities = [multi_asset_volatility] + [single_asset_volatilities[symbol] for symbol in symbols]
plt.subplot(1, 2, 2)
plt.bar(['Multi-Asset'] + symbols, volatilities, color=['blue', 'green', 'red', 'orange'])
plt.title('Portfolio Volatility')
plt.ylabel('Annualized Volatility')

plt.tight_layout()
plt.show()

可得下面結果:
https://ithelp.ithome.com.tw/upload/images/20240923/2012054917WJf0VusH.png
可以看到多資產配置時獲益不錯且波動率不是最高,另外單一資產策略的波動率計算結果出現 0.0 可能有以下原因:

  1. 交易次數不足:對於 AAPLGOOGL,在回測期間,策略可能只有一次買入操作,之後沒有進行賣出或再次買入,導致每日資產價值沒有變化。因此,計算每日收益率時,收益率都是 0,最終導致波動率也為 0.0

  2. 數據記錄問題:可能策略在執行過程中沒有正確記錄每日的組合價值,導致缺少資產價值變化的資訊。

  3. 價格問題:在所選的日期範圍內,某些股票的價格可能變動非常小或保持平穩(例如沒有足夠的歷史波動),因此計算出的波動率為 0.0

如何修正與驗證

  1. 確保策略在 next 方法中正確記錄每日組合價值:檢查是否每一天都成功記錄了組合價值。
  2. 檢查數據完整性:確保在所選的時間範圍內,每個交易日的數據都是完整的,且沒有遺漏。
  3. 檢查單一資產策略的運行情況:確保每個單一資產的策略在回測期間實際進行了交易,或考慮手動記錄每日的資產價值。

調試與改進步驟

為了確保計算波動率時數據的完整性,我們可以打印每個策略的每日組合價值,並檢查 AAPLGOOGL 的波動情況:

# 打印每個策略的每日資產價值
print("Multi-Asset Strategy Final Values:", multi_asset_values)
for symbol in symbols:
    print(f"Single Asset Strategy ({symbol}) Final Values:", single_asset_values[symbol])

查看這些輸出可以幫助你找出問題的根源。如果你仍然看到組合價值沒有變化,請檢查策略是否按預期進行了買入和賣出操作,並確保數據在整個回測期間都是完整和可用的。

五、總結與作業

今天我們學習了多資產投資組合的概念,並實作了一個簡單的投資組合策略。在現實投資中,多資產投資組合可以有效地分散風險,並提高投資組合的穩定性。

今日作業:

  1. 嘗試添加更多不同類型的資產到投資組合中,例如債券ETF房地產ETF等,並觀察對投資組合的影響。
  2. 嘗試使用不同的資產配置方法,看看如何影響投資組合的風險與收益表現。
  3. 研究其他的投資組合優化方法,如均值-方差模型最小方差組合等,並嘗試實現這些策略。至個我們後續也會講到

透過這些練習,你將能夠更加熟悉多資產投資組合的構建與管理,並學會如何在實踐中應用這些技巧,創建更有效的投資組合。


上一篇
Day8:風險管理基礎與風險調整後的收益
下一篇
Day10:因子投資
系列文
打開就會 AI 與數據分析的投資理財術30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言